home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Graphics⁄Sound / Gnome / Gnome.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  16.9 KB  |  786 lines  |  [TEXT/KAHL]

  1. /*
  2.  * Does this restore volume on suspend/exit? (deactivate sufficient?)
  3.  *
  4.  * Gnome -- a Macintosh metronome.
  5.  *
  6.  * This is a TransSkel application (requires TransSkel 2.0 or higher).
  7.  * The project should include Gnome.c, ControlBar.Lib, TransSkel.lib,
  8.  * and MacTraps.
  9.  *
  10.  * This application is public domain, and is written by:
  11.  *
  12.  * Paul DuBois
  13.  * Wisconsin Regional Primate Research Center
  14.  * 1220 Capitol Court
  15.  * Madison, WI  53715-1299  USA
  16.  *
  17.  * Internet:    dubois@primate.wisc.edu
  18.  *
  19.  * 13 Feb 88 Release 1.00
  20.  *
  21.  * 02 Dec 93 Release 1.01
  22.  * - Updated for TransSkel 3.04.  Made multitasking aware; doesn't beat
  23.  * while suspended.  On deactivate/suspend I only make the scrolls inactive.
  24.  * I don't hide and outline them because that looks ugly.
  25.  *
  26.  * 09 Dec 93 Release 1.02
  27.  * - Updated for TransSkel 3.05.
  28.  *
  29.  * 21 Dec 93 Release 1.03
  30.  * - Use color grafport when available.
  31.  * 29 Jan 94
  32.  * - Add outline around Start button, make Return/Enter synonyms for clicking
  33.  * it, and make Escape and Command-period synonyms for clicking Stop button.
  34.  * Command-period is handled in the menu hook.
  35.  *
  36.  * 21 Feb 94 Release 1.04
  37.  * - Updated for TransSkel 3.11, ControlBar 1.05.
  38.  * - Position document window and About alert using TransSkel convenience
  39.  * routines.
  40.  */
  41.  
  42. # include    <Sound.h>
  43.  
  44. # include    "TransSkel.h"
  45.  
  46. # include    "Gnome.h"
  47. # include    "ControlBar.h"
  48.  
  49. # define    normalHilite    0
  50. # define    dimHilite        255
  51.  
  52. # define    returnKey        13
  53. # define    enterKey        3
  54. # define    escapeKey        27
  55.  
  56. # define    nBars        7    /* number of scroll bars */
  57.  
  58. # define    sqSize        15    /* half-size of auditory metronome square */
  59. # define    sqH            365    /* horizontal middle of square */
  60. # define    sqV            110    /* vertical middle of square */
  61.  
  62.  
  63. typedef void (*VoidProcPtr) (void);
  64.  
  65.  
  66. static void    ToneOn (void);
  67. static void    ToneOff (void);
  68. static void    TickOn (void);
  69. static void    TickOff (void);
  70. static VoidProcPtr    SoundOn = TickOn;
  71. static VoidProcPtr    SoundOff = TickOff;
  72. static void    CheckBeat (void);
  73.  
  74. static pascal void BarCheckBeat (ControlHandle bar);
  75. static pascal void SetInitBar (ControlHandle bar);
  76. static pascal void SetVolumeBar (ControlHandle bar);
  77.  
  78. static WindowPtr        gnomeWind;
  79.  
  80. static ControlHandle    startBtn;
  81. static ControlHandle    stopBtn;
  82.  
  83. static ControlHandle    auditoryBox;
  84. static ControlHandle    visualBox;
  85.  
  86. static ControlHandle    tickBox;
  87. static ControlHandle    toneBox;
  88.  
  89. static ControlHandle    initRateBar;
  90. static ControlHandle    finalRateBar;
  91. static ControlHandle    seriesLenBar;
  92. static ControlHandle    pitchBar;
  93. static ControlHandle    rateChgBar;
  94. static ControlHandle    countDownBar;
  95. static ControlHandle    volumeBar;
  96.  
  97. static BarInfo    bar[nBars] =
  98. {
  99.     { &initRateBar, "\pInitial Rate = ", 0, 10, 25, 140,
  100.         1, 400, 60, { 0, "\p" }, SetInitBar, BarCheckBeat },
  101.     { &finalRateBar, "\pFinal Rate = ", 0, 10, 65, 140,
  102.         1, 400, 60, { 0, "\p" }, nil, BarCheckBeat },
  103.     { &rateChgBar, "\pRate Change = ", 0, 10, 105, 140,
  104.         0, 100, 0, { 0, "\p" }, nil, BarCheckBeat },
  105.     { &seriesLenBar, "\pBeats/Rate = ", 0, 10, 145, 140,
  106.         1, 500, 1, { 0, "\p" }, nil, BarCheckBeat },
  107.     { &countDownBar, "\pCountdown Beats = ", 0, 10, 185, 140,
  108.         0, 32, 0, { 0, "\p" }, nil, BarCheckBeat },
  109.     { &pitchBar, "\pPitch = ", 0, 170, 65, 140,
  110.         100, 2000, 880, { 0, "\p" }, nil, BarCheckBeat },
  111.     { &volumeBar, "\pVolume = ", 0, 170, 105, 140,
  112.         0, 31, 0, { 0, "\p" }, SetVolumeBar, BarCheckBeat }
  113. };
  114.  
  115.  
  116. static char            swBuf[sizeof (int) + 2 * sizeof (Tone)];
  117. static SWSynthPtr    sw = (SWSynthPtr) &swBuf;
  118. static char            ffBuf[6+370+370];
  119. static FFSynthPtr    ff = (FFSynthPtr) &ffBuf;
  120.  
  121. static short    on = 0;                /* non-zero if beating */
  122. static short    visual = 1;            /* non-zero if visual metronome enabled */
  123. static short    auditory = 1;        /* non-zero if auditory metronome enabled */
  124. static long    beatStart;            /* when to start next beat */
  125. static long    beatStop;            /* when to stop next beat */
  126. static short    curRate;            /* current metronome rate */
  127. static short    nextRate;            /* metronome rate after next beat */
  128. static short    beatNum;            /* beat number in current series */
  129. static short    inCountDown;        /* non-zero if in countdown series */
  130. static ValInfo    curRateInfo = { -1, "\pXXXXX" };
  131. static ValInfo    beatNumInfo = { -1, "\pXXXXX" };
  132.  
  133. static short    origVolume;
  134.  
  135.  
  136. /* -------------------------------------------------------------------- */
  137. /*    Display routines                                                    */
  138. /* -------------------------------------------------------------------- */
  139.  
  140. /*
  141.  * These functions use ControlBar's UpdateBarNum() function (even though
  142.  * they're not associated with a scroll bar) to minimize flicker.
  143.  */
  144.  
  145. static void
  146. DrawRate (Boolean drawAll)
  147. {
  148. StringPtr    s = "\pCurrent rate = ";
  149. short    h;
  150.  
  151.     if (drawAll)            /* draw title too */
  152.     {
  153.         MoveTo (270, 163);
  154.         DrawString (s);
  155.     }
  156.     h = 270 + StringWidth (s);
  157.     UpdateBarNum (h, 163, on ? curRate : 0, &curRateInfo, drawAll);
  158. }
  159.  
  160.  
  161. static void
  162. DrawBeat (Boolean drawAll)
  163. {
  164. StringPtr    s = "\pCurrent beat = ";
  165. short    h;
  166.  
  167.     if (drawAll)            /* draw title too */
  168.     {
  169.         MoveTo (270, 183);
  170.         DrawString (s);
  171.     }
  172.     h = 270 + StringWidth (s);
  173.     UpdateBarNum (h, 183, on ? beatNum : 0, &beatNumInfo, drawAll);
  174. }
  175.  
  176.  
  177. /* -------------------------------------------------------------------- */
  178. /*    Metronome beat generation control routines                            */
  179. /*        CheckBeat ()    see if time for next beat                        */
  180. /*        StartBeat ()    start next beat                                    */
  181. /*        StopBeat ()        stop current beat                                */
  182. /*        NextBeatTime ()    determine next beat time                        */
  183. /*        StartGnome ()    turn on metronome                                */
  184. /*        StopGnome ()    turn off metronome                                */
  185. /* -------------------------------------------------------------------- */
  186.  
  187.  
  188. /*
  189.  * The Control Manager seems to set the pen to gray while it's tracking
  190.  * a mouse-down in a scroll bar thumb.  This function can be called during
  191.  * tracking, it's necessary to save, set, and restore the pen to avoid
  192.  * drawing in gray.
  193.  */
  194.  
  195. static void
  196. StartBeat (void)
  197. {
  198. PenState    ps;
  199. Rect        r;
  200.  
  201.     ++beatNum;
  202.     DrawBeat (false);
  203.     if (visual)
  204.     {
  205.         SetRect (&r, sqH-sqSize, sqV-sqSize, sqH+sqSize, sqV+sqSize);
  206.         GetPenState (&ps);
  207.         PenNormal ();
  208.         PaintRect (&r);
  209.         SetPenState (&ps);
  210.     }
  211.     if (auditory)
  212.     {
  213.         (*SoundOn)();
  214.     }
  215. }
  216.  
  217.  
  218. static void
  219. StopBeat (void)
  220. {
  221. Rect    r;
  222.  
  223.     SetRect (&r, sqH-sqSize, sqV-sqSize, sqH+sqSize, sqV+sqSize);
  224.     EraseRect (&r);
  225.     (*SoundOff)();
  226. }
  227.  
  228.  
  229. static void
  230. ToneOn (void)
  231. {
  232.     sw->triplets[0].count = 783360L / GetCtlValue (pitchBar);
  233.     sw->triplets[0].duration = 4;
  234.     StartSound (sw, sizeof (swBuf), nil);
  235. }
  236.  
  237.  
  238. static void
  239. ToneOff (void)
  240. {
  241. }
  242.  
  243.  
  244. static void
  245. TickOn (void)
  246. {
  247.     StartSound (ff, sizeof (ffBuf), nil);
  248. }
  249.  
  250.  
  251. static void
  252. TickOff (void)
  253. {
  254.     StopSound ();
  255. }
  256.  
  257.  
  258. static void
  259. StartGnome (void)
  260. {
  261.     on = 1;
  262.     nextRate = GetCtlValue (initRateBar);
  263.     DrawRate (false);
  264.     inCountDown = (GetCtlValue (countDownBar) != 0);
  265.     beatNum = 0;
  266.     beatStart = TickCount ();    /* first beat should occur immediately */
  267. }
  268.  
  269.  
  270. static void
  271. StopGnome (void)
  272. {
  273.     StopBeat ();
  274.     on = 0;
  275.     DrawRate (false);
  276.     DrawBeat (false);
  277. }
  278.  
  279.  
  280. /*
  281.  * This algorithm handles all combinations of parameters.
  282.  * There is no special provision for cases such as constant metronomes
  283.  * (init rate = final rate) or series lengths of 1.  The algorithm
  284.  * could be optimized for such, at the cost of greater complexity.
  285.  *
  286.  * There are 60 ticks/second, 3600 ticks/minute.  Since rate is measured
  287.  * as beats/minute, number of ticks between beats is 3600/curRate.  Not
  288.  * particularly accurate at high rates.  Max achievable rate is 1800
  289.  * ticks a minute.
  290.  */
  291.  
  292. static void
  293. NextBeatTime (void)
  294. {
  295. short    initRate;
  296. short    finalRate;
  297. short    rateChange;
  298.  
  299.     if (curRate != nextRate)
  300.     {
  301.         curRate = nextRate;
  302.         DrawRate (false);
  303.     }
  304.     beatStop = beatStart;
  305.     beatStart = TickCount () + (3600L / curRate);
  306.     beatStop = (beatStart + beatStop) / 2;
  307.     if (inCountDown)
  308.     {
  309.         rateChange = 0;
  310.         if (beatNum >= GetCtlValue (countDownBar))
  311.         {
  312.             inCountDown = 0;    /* done with countdown; start */
  313.             beatNum = 0;        /* first series */
  314.         }
  315.     }
  316.     else
  317.     {
  318.         if (beatNum < GetCtlValue (seriesLenBar))
  319.             rateChange = 0;            /* not done with series */
  320.         else
  321.         {
  322.             rateChange = GetCtlValue (rateChgBar);
  323.             beatNum = 0;
  324.         }
  325.     }
  326.  
  327.     /*
  328.      * Set up rate for next series
  329.      */
  330.  
  331.     initRate = GetCtlValue (initRateBar);
  332.     finalRate = GetCtlValue (finalRateBar);
  333.     if (initRate < finalRate)            /* increasing rate */
  334.     {
  335.         nextRate += rateChange;
  336.         if (nextRate > finalRate)        /* cycle back to initial rate */
  337.             nextRate = initRate;
  338.     }
  339.     else                                /* decreasing or constant rate */
  340.     {
  341.         nextRate -= rateChange;
  342.         if (nextRate < finalRate)        /* cycle back to initial rate */
  343.             nextRate = initRate;
  344.     }
  345. }
  346.  
  347.  
  348. static void
  349. CheckBeat (void)
  350. {
  351. long    t;
  352.  
  353.     if (!on || !SkelQuery (skelQInForeground))
  354.         return;                            /* metronome off or suspended */
  355.     if ((t = TickCount ()) >= beatStart)    /* time for next beat */
  356.     {
  357.         StartBeat ();                /* start beat */
  358.         NextBeatTime ();            /* determine time of next beat, */
  359.                                     /* reset beatNum s'il faut */
  360.     }
  361.     else if (t >= beatStop)
  362.         StopBeat ();
  363. }
  364.  
  365.  
  366. /* -------------------------------------------------------------------- */
  367. /*    Scroll bar and button handler routines                                */
  368. /* -------------------------------------------------------------------- */
  369.  
  370.  
  371. /*
  372.  * Set sound volume.  The amplitude of the wave modulates within
  373.  * each SetSoundVol() level to attain variation between
  374.  * 0 and 31, rather than between 0 and 7.
  375.  */
  376.  
  377. static void
  378. SetSound (short vol)
  379. {
  380.     SetSoundVol (vol/4);
  381.     if (vol > 0)
  382.     {
  383.         switch (vol % 4)
  384.         {
  385.             case 0: vol = 180; break;
  386.             case 1: vol = 205; break;
  387.             case 2: vol = 230; break;
  388.             case 3: vol = 255; break;
  389.         }
  390.     }
  391.     sw->triplets[0].amplitude = vol;
  392. }
  393.  
  394. /*
  395.  * Make rate follow initial rate if mouse down in initRateBar
  396.  */
  397.  
  398. static pascal void
  399. SetInitBar (ControlHandle bar)
  400. {
  401.     nextRate = GetCtlValue (bar);
  402.     DrawRate (false);
  403. }
  404.  
  405.  
  406. static pascal void
  407. SetVolumeBar (ControlHandle bar)
  408. {
  409.     SetSound (GetCtlValue (bar));
  410. }
  411.  
  412.  
  413. /*
  414.  * This is the idle function for all the bars.  It simply calls CheckBeat()
  415.  * to see whether a new beat needs to be generated during bar mouse tracking.
  416.  * It's shared among them and the particular bar is irrelevant.
  417.  */
  418.  
  419. static pascal void
  420. BarCheckBeat (ControlHandle bar)
  421. {
  422.     CheckBeat ();
  423. }
  424.  
  425.  
  426. /*
  427.  * Check for next beat while mouse down in button
  428.  */
  429.  
  430. static pascal void
  431. TrackButton (ControlHandle ctrl, short partCode)
  432. {
  433.     CheckBeat ();
  434. }
  435.  
  436.  
  437. /* -------------------------------------------------------------------- */
  438. /*    Window handler routines                                                */
  439. /* -------------------------------------------------------------------- */
  440.  
  441.  
  442. /*
  443.     Process mouse hit in control.
  444. */
  445.  
  446. static pascal void
  447. Mouse (Point pt, long t, short mods)
  448. {
  449. ControlHandle    ctrl;
  450. short            trackPart;
  451.  
  452.     if ((trackPart = FindControl (pt, gnomeWind, &ctrl)) != 0)
  453.     {
  454.         if (trackPart == inButton)        /* start or stop button */
  455.         {
  456.             if (TrackControl (ctrl, pt, TrackButton) != 0)
  457.             {
  458.                 if (ctrl == startBtn)
  459.                     StartGnome ();
  460.                 else
  461.                     StopGnome ();
  462.             }
  463.         }
  464.         else if (trackPart == inCheckBox)
  465.         {
  466.             if (TrackControl (ctrl, pt, TrackButton) != 0)
  467.             {
  468.                 if (ctrl == tickBox)
  469.                 {
  470.                     SoundOn = TickOn;
  471.                     SoundOff = TickOff;
  472.                     SetCtlValue (tickBox, 1);
  473.                     SetCtlValue (toneBox, 0);
  474.                     HiliteControl (pitchBar, dimHilite);
  475.                 }
  476.                 else if (ctrl == toneBox)
  477.                 {
  478.                     SoundOn = ToneOn;
  479.                     SoundOff = ToneOff;
  480.                     SetCtlValue (tickBox, 0);
  481.                     SetCtlValue (toneBox, 1);
  482.                     HiliteControl (pitchBar, normalHilite);
  483.                 }
  484.                 else if (ctrl == auditoryBox)
  485.                 {
  486.                     SetCtlValue (ctrl, auditory = !GetCtlValue (ctrl));
  487.                 }
  488.                 else
  489.                 {
  490.                     SetCtlValue (ctrl, visual = !GetCtlValue (ctrl));
  491.                 }
  492.             }
  493.         }
  494.         else
  495.             TrackBar (ctrl, pt, trackPart);
  496.     }
  497. }
  498.  
  499.  
  500. static pascal void
  501. Key (short c, short code, short mods)
  502. {
  503.     if (c == returnKey || c == enterKey)
  504.     {
  505.         SkelFlashButton (startBtn);
  506.         StartGnome ();
  507.     }
  508.     else if (c == escapeKey)
  509.     {
  510.         SkelFlashButton (stopBtn);
  511.         StopGnome ();
  512.     }
  513. }
  514.         
  515.  
  516. static pascal void
  517. Update (Boolean resized)
  518. {
  519. short    i;
  520.  
  521.     MoveTo (202, 20);
  522.     DrawString ("\pSound Type");
  523.     DrawControls (gnomeWind);
  524.     SkelDrawButtonOutline (startBtn);
  525.     for (i = 0; i < nBars; i++)
  526.     {
  527.         DrawBarTitle (*bar[i].bBar);
  528.         DrawBarValue (*bar[i].bBar, true);
  529.     }
  530.     DrawRate (true);
  531.     DrawBeat (true);
  532. }
  533.  
  534.  
  535. static pascal void
  536. Activate (Boolean active)
  537. {
  538. ControlHandle    ctrl;
  539. short        i;
  540. short        hilite = (active ? normalHilite : dimHilite);
  541.  
  542.     if (!active)    /* deactivated */
  543.     {
  544.         StopBeat ();
  545.         SetSoundVol (origVolume);
  546.     }
  547.     else
  548.     {
  549.         SetSound (GetCtlValue (volumeBar));
  550.     }
  551.  
  552.     HiliteControl (startBtn, hilite);
  553.     SkelDrawButtonOutline (startBtn);
  554.     HiliteControl (stopBtn, hilite);
  555.     HiliteControl (auditoryBox, hilite);
  556.     HiliteControl (visualBox, hilite);
  557.     HiliteControl (tickBox, hilite);
  558.     HiliteControl (toneBox, hilite);
  559.     for (i = 0; i < nBars; i++)
  560.     {
  561.         ctrl =*bar[i].bBar;
  562.         if (ctrl == pitchBar && active)
  563.         {
  564.             if (GetCtlValue (toneBox) != 0)
  565.                 HiliteControl (ctrl, normalHilite);
  566.             else
  567.                 HiliteControl (ctrl, dimHilite);
  568.             
  569.         }
  570.         else
  571.             HiliteControl (ctrl, hilite);
  572.         DrawBarValue (*bar[i].bBar, true);
  573.     }
  574. }
  575.  
  576.  
  577. static pascal void
  578. Clobber (void)
  579. {
  580.     HideWindow (gnomeWind);
  581.     DisposeWindow (gnomeWind);
  582. }
  583.  
  584.  
  585. /* -------------------------------------------------------------------- */
  586. /*    Menu handlers                                                        */
  587. /* -------------------------------------------------------------------- */
  588.  
  589.  
  590. /*
  591.  * Handle "About Gnome..." selection from Apple menu.
  592.  */
  593.  
  594. static pascal void
  595. DoAppleMenu (short item)
  596. {
  597.     (void) SkelAlert (aboutAlrtNum, SkelDlogFilter (nil, true),
  598.                                         skelPositionOnParentDevice);
  599.     SkelRmveDlogFilter ();
  600. }
  601.  
  602.  
  603. static pascal void
  604. DoFileMenu (short item)
  605. {
  606.     StopBeat ();
  607.     SkelStopEventLoop ();    /* only one item -- Quit */
  608. }
  609.  
  610.  
  611. /* -------------------------------------------------------------------- */
  612. /*    Application idle-time function                                        */
  613. /* -------------------------------------------------------------------- */
  614.  
  615.  
  616. static pascal void
  617. Idle (void)
  618. {
  619.     CheckBeat ();
  620. }
  621.  
  622.  
  623. /* -------------------------------------------------------------------- */
  624. /*    Menu hook                                                            */
  625. /* -------------------------------------------------------------------- */
  626.  
  627.  
  628. /*
  629.  * Command-period is mapped to the Stop button, but it has to be caught
  630.  * in a menu hook function since otherwise it will be ignored.  (Since
  631.  * it's a command-key event, it's not passed to the Key() function.)
  632.  */
  633.  
  634. static pascal void
  635. MyMenuHook (void)
  636. {
  637.     if (SkelCmdPeriod (SkelGetCurrentEvent ()))
  638.     {
  639.         SkelFlashButton (stopBtn);
  640.         StopGnome ();
  641.     }
  642. }
  643.  
  644.  
  645. /* -------------------------------------------------------------------- */
  646. /*    Suspend/resume handler                                                */
  647. /* -------------------------------------------------------------------- */
  648.  
  649.  
  650. static pascal void
  651. SuspendResume (Boolean inForeground)
  652. {
  653.     SkelActivate (FrontWindow (), inForeground);
  654. }
  655.  
  656.  
  657. /* -------------------------------------------------------------------- */
  658. /*    Initialization                                                        */
  659. /* -------------------------------------------------------------------- */
  660.  
  661.  
  662. static void
  663. MenuInit ()
  664. {
  665. MenuHandle    m;
  666.  
  667.     SkelApple ("\pAbout Gnome\311", DoAppleMenu);
  668.     m = NewMenu (1000, "\pFile");
  669.     AppendMenu (m, "\pQuit/Q");
  670.     (void) SkelMenu (m, DoFileMenu, nil, false, false);
  671.     DrawMenuBar ();
  672. }
  673.  
  674. static void
  675. WaveInit (void)
  676. {
  677. short    i;
  678.  
  679.     sw->mode = swMode;
  680.     /* triplet[0] set later */
  681.     sw->triplets[1].count = 0;
  682.     sw->triplets[1].amplitude = 0;
  683.     sw->triplets[1].duration = 0;
  684.  
  685.     ff->mode = ffMode;
  686.     ff->count = 0x10000;    /* 1.0 in fixed notation */
  687.     for (i = 6; i < sizeof (ffBuf); ++i)
  688.     {
  689.         ffBuf[i] = Random () & 255;    /* 0 .. 255 */
  690.         if (ffBuf[i] < 128)
  691.             ffBuf[i] += 128;
  692.     }
  693. }
  694.  
  695.  
  696. static void
  697. WindInit (void)
  698. {
  699. Rect    r;
  700. short    i;
  701.  
  702.     SetRect (&r, 0, 0, 415, 210);
  703.     if (SkelQuery (skelQHasColorQD))
  704.     {
  705.         gnomeWind = NewCWindow (nil, &r, "\pGnome", false, noGrowDocProc,
  706.                                 (WindowPtr) -1L, false, 0L);
  707.     }
  708.     else
  709.     {
  710.         gnomeWind = NewWindow (nil, &r, "\pGnome", false, noGrowDocProc,
  711.                                 (WindowPtr) -1L, false, 0L);
  712.     }
  713.     SkelPositionWindow (gnomeWind, skelPositionOnMainDevice,
  714.                                     FixRatio (1, 2), FixRatio (1, 5));
  715.     (void) SkelWindow (gnomeWind,
  716.                 Mouse,
  717.                 Key,
  718.                 Update,
  719.                 Activate,
  720.                 nil,
  721.                 Clobber,
  722.                 nil,
  723.                 true);
  724.  
  725.     TextFont (0);
  726.     TextSize (0);
  727.  
  728.     /*
  729.      * Make controls for window.
  730.      */
  731.  
  732.     SetRect (&r, 330, 15, 400, 35);
  733.     startBtn = NewControl (gnomeWind, &r, "\pStart", true, 0, 0, 1,
  734.                         pushButProc, 0L);
  735.     OffsetRect (&r, 0, 35);
  736.     stopBtn = NewControl (gnomeWind, &r, "\pStop", true, 0, 0, 1,
  737.                         pushButProc, 0L);
  738.  
  739.     SetRect (&r, 183, 24, 243, 40);
  740.     toneBox = NewControl (gnomeWind, &r, "\pTone", true,
  741.                         0, 0, 1, radioButProc, 0L);
  742.     OffsetRect (&r, 70, 0);
  743.     tickBox = NewControl (gnomeWind, &r, "\pTick", true,
  744.                         1, 0, 1, radioButProc, 0L);
  745.  
  746.     SetRect (&r, 168, 150, 268, 166);
  747.     auditoryBox = NewControl (gnomeWind, &r, "\pAuditory", true,
  748.                         auditory, 0, 1, checkBoxProc, 0L);
  749.     OffsetRect (&r, 0, 20);
  750.     visualBox = NewControl (gnomeWind, &r, "\pVisual", true,
  751.                         visual, 0, 1, checkBoxProc, 0L);
  752.  
  753.     for (i = 0; i < nBars; i++)
  754.     {
  755.         MakeBar (&bar[i], gnomeWind);
  756.     }
  757.     
  758.     GetSoundVol (&i);
  759.     i *= 4;
  760.     SetBarValue (volumeBar, i);
  761.     
  762.     HiliteControl (pitchBar, dimHilite);
  763.     
  764.     ShowWindow (gnomeWind);        /* done initializing; make visible */
  765. }
  766.  
  767.  
  768. /* -------------------------------------------------------------------- */
  769.  
  770.  
  771. int
  772. main (void)
  773. {
  774.     SkelInit ((SkelInitParamsPtr) nil);
  775.     GetSoundVol (&origVolume);
  776.     randSeed = TickCount ();
  777.     MenuInit ();
  778.     WaveInit ();
  779.     WindInit ();
  780.     SkelSetIdle (Idle);
  781.     SkelSetSuspendResume (SuspendResume);
  782.     SkelSetMenuHook (MyMenuHook);
  783.     SkelEventLoop ();
  784.     SetSoundVol (origVolume);
  785.     SkelCleanup ();
  786. }